package com.stylefeng.guns.crawlers.okooo;

import cn.wanghaomiao.seimi.annotation.Crawler;
import cn.wanghaomiao.seimi.core.SeimiBeanResolver;
import cn.wanghaomiao.seimi.def.BaseSeimiCrawler;
import cn.wanghaomiao.seimi.struct.Request;
import cn.wanghaomiao.seimi.struct.Response;
import com.stylefeng.guns.common.persistence.dao.HistoryMapper;
import com.stylefeng.guns.common.persistence.dao.GameMapper;
import com.stylefeng.guns.common.persistence.model.History;
import com.stylefeng.guns.common.persistence.model.Game;
import com.stylefeng.guns.crawlers.okooo.model.OkoooGameContent;
import org.apache.commons.lang3.StringUtils;
import org.seimicrawler.xpath.JXDocument;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.util.CollectionUtils;

import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 澳客数据爬虫
 *
 * @author github.com/zhegexiaohuozi seimimaster@gmail.com
 * @since 2016/07/27.
 */
@Crawler(name = "okoooGame")
public class OkoooGameCrawler extends BaseSeimiCrawler {

    @Autowired
    private GameMapper gameMapper;

    @Autowired
    private HistoryMapper historyMapper;

    private static final String MATCHER_PATTERN = "match/(\\d+?)/history";

    @Override
    public String[] startUrls() {
        return null;
    }

    @Override
    public List<Request> startRequests() {
        List<Request> requests = new LinkedList<>();
        Request start = Request.build("http://www.okooo.com/okooo/", "start");
        Map<String, Object> params = new HashMap<>();
        params.put("liansai", "英超,意甲,西甲,德甲,法甲");
        start.setMeta(params);
        requests.add(start);
        return requests;
    }

    @Override
    public void start(Response response) {
        JXDocument doc = response.document();
        Map<String, Object> params = response.getRequest().getMeta();
        String[] liansai = params.get("liansai").toString().split(",");
        try {
            List<Object> elements = doc.sel("//div[@class='touzhu_1'][@data-end='0']");
            logger.info("{}", elements.size());
            elements.forEach(object -> {
                JXDocument childDoc = JXDocument.create(object.toString());
                OkoooGameContent gameContent = null;
                try {
                    gameContent = SeimiBeanResolver.parse(OkoooGameContent.class, object.toString());
                    // 为五大联赛
                    if (Arrays.asList(liansai).contains(gameContent.getTitle())) {

                        // 获取分析数据url
                        List<Object> history1 = childDoc.sel("//div[@class='historyn1']/a/@href");
                        // 拼装请求
                        String historyUrl = "http://www.okooo.com" + history1.get(1).toString();
                        Request request = Request.build(historyUrl, OkoooGameCrawler::parseHistoryData).setSkipDuplicateFilter(true);
                        Map<String, Object> map = new HashMap<>();
                        map.put("dataMid", gameContent.getMid());
                        map.put("title", gameContent.getTitle());
                        map.put("content", gameContent);
                        request.setMeta(map);
                        // 发起请求
                        push(request);
                    }
                } catch (Exception e) {
                    logger.warn("爬取竞彩数据数据【{}】失败", gameContent, e);
                }
            });

        } catch (Exception e) {
            logger.error("爬取错误", e);
        }
    }


    /**
     * 分析数据存储
     *
     * @param response
     */
    public void parseHistoryData(Response response) {

        Map<String, Object> params = response.getRequest().getMeta();
        String dataMid = (String) params.get("mid");
        String pTitle = (String) params.get("title");
        OkoooGameContent gameContent = (OkoooGameContent) params.get("content");
        try {
            JXDocument jxDocument = response.document();

            Game game = new Game();
            game.setMid(gameContent.getMid());
            game.setTitle(gameContent.getTitle());
            game.setZhud(gameContent.getZhud());
            game.setKed(gameContent.getKed());
            game.setTime(StringUtils.substringAfter(gameContent.getTime(), ":"));
            gameMapper.insert(game);

            List<Object> types = jxDocument.sel("//div[@class='lsdata']/table/@class");
            logger.warn("联赛数据种类有：{}", types);
            // 获取主队的进6场联赛
            types.forEach(type -> {
                List<Object> objects = jxDocument.sel("//table[@class='" + type + "']//tr[@data-lt='league']");
                List<History> histories = objects.stream().map(x -> {
                    JXDocument jxDocument1 = JXDocument.create(x.toString());
                    // 联赛名
                    Object title = jxDocument1.selOne("//a[1]/text()");
                    if (pTitle.equals(title)) {
                        // 比赛时间
                        Object time = jxDocument1.selOne("//a[2]/text()");
                        // 比分
                        Object score = jxDocument1.selOne("//a[4]/text()");
                        String[] scores = StringUtils.split(score.toString(), "-");
                        // 主队
                        Object mainTeam = jxDocument1.selOne("//a[3]/span/text()");
                        if ("".equals(mainTeam) || mainTeam == null) {
                            mainTeam = jxDocument1.selOne("//a[3]/text()");
                        }
                        // 客队
                        Object otherTeam = jxDocument1.selOne("//a[5]/text()");
                        if ("".equals(otherTeam) || otherTeam == null) {
                            otherTeam = jxDocument1.selOne("//a[5]/span/text()");
                        }
                        // 总进球数
                        Integer goal = Arrays.stream(scores).mapToInt(Integer::valueOf).sum();

                        History history = new History();
                        history.setMid(dataMid);
                        history.setTitle(title.toString());
                        history.setTime(time.toString());
                        history.setZhud(mainTeam.toString());
                        history.setKeyd(otherTeam.toString());
                        history.setGoal(goal);
                        history.setScore(score.toString());
                        history.setCompType(type.toString());
                        return history;
                    }
                    return null;
                }).collect(Collectors.toList());

                if (!CollectionUtils.isEmpty(histories)) {
                    histories = histories.stream().filter(Objects::nonNull).sorted(Comparator.comparing(History::getTime).reversed()).collect(Collectors.toList());
                    if (histories.size() > 6) {
                        histories = histories.subList(0, 6);
                    }
                    try {
                        // 插入分析数据
                        historyMapper.insertList(histories);
                    } catch (Exception e) {
                        logger.info("错误数据为={}", histories);
                    }
                }

            });

        } catch (DataAccessException e) {
            logger.info("重复爬取竞彩数据【{}】", gameContent);
        }
    }

    public String getDataMid(String url) {
        Pattern pattern = Pattern.compile(MATCHER_PATTERN);
        Matcher matcher = pattern.matcher(url);
        if (matcher.find()) {
            return matcher.group(1);
        }
        return "";
    }

}
